/**
 * 游戏错误处理器
 * 统一管理游戏中的所有错误处理，整合渲染、音频、存储等各种错误处理器
 * 提供全局错误监控和恢复机制
 * @class
 */

import { RenderErrorHandler, renderErrorHandler, type RenderErrorInfo } from './RenderErrorHandler'
import { AudioErrorHandler, audioErrorHandler, type AudioErrorInfo } from './AudioErrorHandler'
import { StorageErrorHandler, storageErrorHandler, type StorageErrorInfo } from './StorageErrorHandler'

export interface GameErrorHandlerOptions {
  /** 是否启用全局错误监控 */
  enableGlobalErrorHandling?: boolean
  /** 是否启用错误报告 */
  enableErrorReporting?: boolean
  /** 错误报告的端点URL */
  errorReportingEndpoint?: string
  /** 是否在开发模式下显示详细错误 */
  showDetailedErrors?: boolean
  /** 错误恢复尝试次数 */
  maxRecoveryAttempts?: number
}

export interface GameErrorInfo {
  /** 错误ID */
  id: string
  /** 错误类型 */
  type: 'render' | 'audio' | 'storage' | 'game' | 'network' | 'unknown'
  /** 错误级别 */
  level: 'low' | 'medium' | 'high' | 'critical'
  /** 错误消息 */
  message: string
  /** 错误对象 */
  error: Error
  /** 发生错误的时间戳 */
  timestamp: number
  /** 错误堆栈 */
  stack?: string
  /** 用户代理信息 */
  userAgent?: string
  /** 页面URL */
  url?: string
  /** 错误上下文 */
  context?: any
  /** 是否已恢复 */
  recovered?: boolean
  /** 恢复尝试次数 */
  recoveryAttempts?: number
}

export interface GameState {
  /** 游戏是否正在运行 */
  isRunning: boolean
  /** 游戏是否暂停 */
  isPaused: boolean
  /** 当前关卡 */
  currentLevel: number
  /** 玩家分数 */
  score: number
  /** 错误计数 */
  errorCount: number
}

/**
 * 游戏错误处理器类
 */
export class GameErrorHandler {
  private options: Required<GameErrorHandlerOptions>
  private renderErrorHandler: RenderErrorHandler
  private audioErrorHandler: AudioErrorHandler
  private storageErrorHandler: StorageErrorHandler
  private errorHistory: GameErrorInfo[] = []
  private maxErrorHistory: number = 100
  private errorCallbacks: Array<(error: GameErrorInfo) => void> = []
  private recoveryCallbacks: Array<(error: GameErrorInfo) => boolean> = []
  private gameState: GameState = {
    isRunning: false,
    isPaused: false,
    currentLevel: 1,
    score: 0,
    errorCount: 0
  }
  private errorIdCounter: number = 0
  private isInitialized: boolean = false

  /**
   * 创建游戏错误处理器
   * @param options - 配置选项
   */
  constructor(options: GameErrorHandlerOptions = {}) {
    this.options = {
      enableGlobalErrorHandling: options.enableGlobalErrorHandling ?? true,
      enableErrorReporting: options.enableErrorReporting ?? false,
      errorReportingEndpoint: options.errorReportingEndpoint ?? '',
      showDetailedErrors: options.showDetailedErrors ?? process.env.NODE_ENV === 'development',
      maxRecoveryAttempts: options.maxRecoveryAttempts ?? 3
    }

    // 初始化子错误处理器
    this.renderErrorHandler = renderErrorHandler
    this.audioErrorHandler = audioErrorHandler
    this.storageErrorHandler = storageErrorHandler

    // 设置子错误处理器的回调
    this.setupSubHandlerCallbacks()
  }

  /**
   * 初始化错误处理器
   */
  initialize(): void {
    if (this.isInitialized) {
      return
    }

    // 设置全局错误监控
    if (this.options.enableGlobalErrorHandling) {
      this.setupGlobalErrorHandling()
    }

    this.isInitialized = true
    console.log('GameErrorHandler 初始化完成')
  }

  /**
   * 设置子错误处理器的回调
   */
  private setupSubHandlerCallbacks(): void {
    // 渲染错误回调
    this.renderErrorHandler.addErrorCallback((renderError: RenderErrorInfo) => {
      const gameError: GameErrorInfo = {
        id: this.generateErrorId(),
        type: 'render',
        level: this.getErrorLevel(renderError.type),
        message: renderError.message,
        error: renderError.error,
        timestamp: renderError.timestamp,
        stack: renderError.error.stack,
        context: renderError.context
      }
      this.handleError(gameError)
    })

    // 音频错误回调
    this.audioErrorHandler.addErrorCallback((audioError: AudioErrorInfo) => {
      const gameError: GameErrorInfo = {
        id: this.generateErrorId(),
        type: 'audio',
        level: this.getAudioErrorLevel(audioError.type),
        message: audioError.message,
        error: audioError.error,
        timestamp: audioError.timestamp,
        stack: audioError.error.stack,
        context: audioError.context
      }
      this.handleError(gameError)
    })

    // 存储错误回调
    this.storageErrorHandler.addErrorCallback((storageError: StorageErrorInfo) => {
      const gameError: GameErrorInfo = {
        id: this.generateErrorId(),
        type: 'storage',
        level: this.getStorageErrorLevel(storageError.type),
        message: storageError.message,
        error: storageError.error,
        timestamp: storageError.timestamp,
        stack: storageError.error.stack,
        context: storageError.context
      }
      this.handleError(gameError)
    })
  }

  /**
   * 设置全局错误监控
   */
  private setupGlobalErrorHandling(): void {
    // 监听未捕获的JavaScript错误
    window.addEventListener('error', (event) => {
      const gameError: GameErrorInfo = {
        id: this.generateErrorId(),
        type: 'game',
        level: 'high',
        message: `未捕获的错误: ${event.message}`,
        error: new Error(event.message),
        timestamp: Date.now(),
        stack: event.error?.stack,
        userAgent: navigator.userAgent,
        url: event.filename,
        context: {
          lineno: event.lineno,
          colno: event.colno
        }
      }
      this.handleError(gameError)
    })

    // 监听未处理的Promise拒绝
    window.addEventListener('unhandledrejection', (event) => {
      const gameError: GameErrorInfo = {
        id: this.generateErrorId(),
        type: 'game',
        level: 'medium',
        message: `未处理的Promise拒绝: ${event.reason}`,
        error: event.reason instanceof Error ? event.reason : new Error(String(event.reason)),
        timestamp: Date.now(),
        stack: event.reason?.stack,
        userAgent: navigator.userAgent,
        url: window.location.href
      }
      this.handleError(gameError)
    })

    // 监听资源加载错误
    window.addEventListener('error', (event) => {
      if (event.target && event.target !== window) {
        const target = event.target as HTMLElement
        const gameError: GameErrorInfo = {
          id: this.generateErrorId(),
          type: 'network',
          level: 'medium',
          message: `资源加载失败: ${target.tagName}`,
          error: new Error('Resource loading failed'),
          timestamp: Date.now(),
          userAgent: navigator.userAgent,
          url: window.location.href,
          context: {
            tagName: target.tagName,
            src: (target as any).src || (target as any).href
          }
        }
        this.handleError(gameError)
      }
    }, true)
  }

  /**
   * 处理错误
   * @param error - 游戏错误信息
   */
  private handleError(error: GameErrorInfo): void {
    // 记录错误
    this.logError(error)

    // 更新游戏状态
    this.gameState.errorCount++

    // 尝试恢复
    const recovered = this.attemptRecovery(error)
    error.recovered = recovered

    // 触发错误回调
    this.errorCallbacks.forEach(callback => {
      try {
        callback(error)
      } catch (callbackError) {
        console.error('错误回调执行失败:', callbackError)
      }
    })

    // 报告错误（如果启用）
    if (this.options.enableErrorReporting) {
      this.reportError(error)
    }

    // 显示错误信息（开发模式）
    if (this.options.showDetailedErrors) {
      this.showErrorDetails(error)
    }
  }

  /**
   * 尝试错误恢复
   * @param error - 错误信息
   * @returns 是否成功恢复
   */
  private attemptRecovery(error: GameErrorInfo): boolean {
    if (!error.recoveryAttempts) {
      error.recoveryAttempts = 0
    }

    if (error.recoveryAttempts >= this.options.maxRecoveryAttempts) {
      console.warn(`错误 ${error.id} 已达到最大恢复尝试次数`)
      return false
    }

    error.recoveryAttempts++

    // 尝试自动恢复
    let recovered = false

    switch (error.type) {
      case 'render':
        recovered = this.recoverFromRenderError(error)
        break
      case 'audio':
        recovered = this.recoverFromAudioError(error)
        break
      case 'storage':
        recovered = this.recoverFromStorageError(error)
        break
      case 'game':
        recovered = this.recoverFromGameError(error)
        break
      case 'network':
        recovered = this.recoverFromNetworkError(error)
        break
    }

    // 尝试自定义恢复回调
    if (!recovered) {
      for (const callback of this.recoveryCallbacks) {
        try {
          if (callback(error)) {
            recovered = true
            break
          }
        } catch (callbackError) {
          console.error('恢复回调执行失败:', callbackError)
        }
      }
    }

    if (recovered) {
      console.log(`错误 ${error.id} 恢复成功`)
    } else {
      console.warn(`错误 ${error.id} 恢复失败`)
    }

    return recovered
  }

  /**
   * 从渲染错误中恢复
   * @param error - 错误信息
   * @returns 是否成功恢复
   */
  private recoverFromRenderError(error: GameErrorInfo): boolean {
    // 渲染错误通常由RenderErrorHandler处理
    // 这里可以添加额外的游戏级恢复逻辑
    
    if (error.level === 'critical') {
      // 重启游戏引擎
      console.log('尝试重启游戏引擎')
      return this.restartGameEngine()
    }

    return false
  }

  /**
   * 从音频错误中恢复
   * @param error - 错误信息
   * @returns 是否成功恢复
   */
  private recoverFromAudioError(error: GameErrorInfo): boolean {
    // 音频错误通常不影响游戏核心功能
    // 可以继续游戏但禁用音频
    console.log('音频错误，继续无声游戏')
    return true
  }

  /**
   * 从存储错误中恢复
   * @param error - 错误信息
   * @returns 是否成功恢复
   */
  private recoverFromStorageError(error: GameErrorInfo): boolean {
    // 存储错误通常由StorageErrorHandler处理
    // 这里可以添加游戏状态的备份和恢复逻辑
    console.log('存储错误，使用内存模式继续游戏')
    return true
  }

  /**
   * 从游戏错误中恢复
   * @param error - 错误信息
   * @returns 是否成功恢复
   */
  private recoverFromGameError(error: GameErrorInfo): boolean {
    if (error.level === 'critical') {
      // 重启游戏
      console.log('严重游戏错误，尝试重启游戏')
      return this.restartGame()
    }

    // 尝试重置游戏状态
    console.log('尝试重置游戏状态')
    return this.resetGameState()
  }

  /**
   * 从网络错误中恢复
   * @param error - 错误信息
   * @returns 是否成功恢复
   */
  private recoverFromNetworkError(error: GameErrorInfo): boolean {
    // 网络错误通常是资源加载失败
    // 可以尝试重新加载或使用默认资源
    console.log('网络错误，使用默认资源')
    return true
  }

  /**
   * 重启游戏引擎
   * @returns 是否成功重启
   */
  private restartGameEngine(): boolean {
    try {
      // 这里应该调用实际的游戏引擎重启逻辑
      console.log('游戏引擎重启成功')
      return true
    } catch (error) {
      console.error('游戏引擎重启失败:', error)
      return false
    }
  }

  /**
   * 重启游戏
   * @returns 是否成功重启
   */
  private restartGame(): boolean {
    try {
      // 重置游戏状态
      this.gameState = {
        isRunning: false,
        isPaused: false,
        currentLevel: 1,
        score: 0,
        errorCount: 0
      }
      
      console.log('游戏重启成功')
      return true
    } catch (error) {
      console.error('游戏重启失败:', error)
      return false
    }
  }

  /**
   * 重置游戏状态
   * @returns 是否成功重置
   */
  private resetGameState(): boolean {
    try {
      // 保留分数和关卡，只重置运行状态
      this.gameState.isRunning = true
      this.gameState.isPaused = false
      
      console.log('游戏状态重置成功')
      return true
    } catch (error) {
      console.error('游戏状态重置失败:', error)
      return false
    }
  }

  /**
   * 获取渲染错误级别
   * @param errorType - 渲染错误类型
   * @returns 错误级别
   */
  private getErrorLevel(errorType: string): 'low' | 'medium' | 'high' | 'critical' {
    const levelMap: Record<string, 'low' | 'medium' | 'high' | 'critical'> = {
      'canvas': 'critical',
      'context': 'high',
      'animation': 'medium',
      'texture': 'low',
      'shader': 'medium'
    }
    return levelMap[errorType] || 'medium'
  }

  /**
   * 获取音频错误级别
   * @param errorType - 音频错误类型
   * @returns 错误级别
   */
  private getAudioErrorLevel(errorType: string): 'low' | 'medium' | 'high' | 'critical' {
    const levelMap: Record<string, 'low' | 'medium' | 'high' | 'critical'> = {
      'context': 'medium',
      'loading': 'low',
      'playback': 'low',
      'decoding': 'medium',
      'permission': 'medium'
    }
    return levelMap[errorType] || 'low'
  }

  /**
   * 获取存储错误级别
   * @param errorType - 存储错误类型
   * @returns 错误级别
   */
  private getStorageErrorLevel(errorType: string): 'low' | 'medium' | 'high' | 'critical' {
    const levelMap: Record<string, 'low' | 'medium' | 'high' | 'critical'> = {
      'quota': 'medium',
      'access': 'high',
      'corruption': 'high',
      'permission': 'medium',
      'serialization': 'low'
    }
    return levelMap[errorType] || 'medium'
  }

  /**
   * 生成错误ID
   * @returns 唯一的错误ID
   */
  private generateErrorId(): string {
    return `error_${Date.now()}_${++this.errorIdCounter}`
  }

  /**
   * 记录错误信息
   * @param error - 错误信息
   */
  private logError(error: GameErrorInfo): void {
    this.errorHistory.push(error)
    
    // 限制错误历史记录数量
    if (this.errorHistory.length > this.maxErrorHistory) {
      this.errorHistory.shift()
    }

    // 根据错误级别选择日志方法
    const logMethod = error.level === 'critical' ? console.error :
                     error.level === 'high' ? console.error :
                     error.level === 'medium' ? console.warn : console.log

    logMethod(`[GameErrorHandler] ${error.message}`, {
      id: error.id,
      type: error.type,
      level: error.level,
      error: error.error,
      context: error.context
    })
  }

  /**
   * 报告错误到服务器
   * @param error - 错误信息
   */
  private async reportError(error: GameErrorInfo): Promise<void> {
    if (!this.options.errorReportingEndpoint) {
      return
    }

    try {
      const reportData = {
        id: error.id,
        type: error.type,
        level: error.level,
        message: error.message,
        stack: error.stack,
        timestamp: error.timestamp,
        userAgent: error.userAgent,
        url: error.url,
        context: error.context,
        gameState: this.gameState
      }

      await fetch(this.options.errorReportingEndpoint, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(reportData)
      })

      console.log(`错误 ${error.id} 已报告到服务器`)
    } catch (reportError) {
      console.error('错误报告失败:', reportError)
    }
  }

  /**
   * 显示错误详情（开发模式）
   * @param error - 错误信息
   */
  private showErrorDetails(error: GameErrorInfo): void {
    const details = document.createElement('div')
    details.className = 'error-details'
    details.style.cssText = `
      position: fixed;
      top: 10px;
      left: 10px;
      background: rgba(220, 53, 69, 0.95);
      color: white;
      padding: 15px;
      border-radius: 6px;
      font-family: monospace;
      font-size: 12px;
      z-index: 9999;
      max-width: 500px;
      max-height: 300px;
      overflow: auto;
      white-space: pre-wrap;
    `
    details.innerHTML = `
      <strong>错误详情 (开发模式)</strong>
      ID: ${error.id}
      类型: ${error.type}
      级别: ${error.level}
      消息: ${error.message}
      时间: ${new Date(error.timestamp).toLocaleString()}
      ${error.stack ? `\n堆栈:\n${error.stack}` : ''}
      ${error.context ? `\n上下文:\n${JSON.stringify(error.context, null, 2)}` : ''}
    `

    document.body.appendChild(details)

    // 10秒后移除
    setTimeout(() => {
      details.remove()
    }, 10000)
  }

  /**
   * 更新游戏状态
   * @param state - 新的游戏状态
   */
  updateGameState(state: Partial<GameState>): void {
    this.gameState = { ...this.gameState, ...state }
  }

  /**
   * 获取游戏状态
   * @returns 当前游戏状态
   */
  getGameState(): GameState {
    return { ...this.gameState }
  }

  /**
   * 添加错误回调函数
   * @param callback - 错误回调函数
   */
  addErrorCallback(callback: (error: GameErrorInfo) => void): void {
    this.errorCallbacks.push(callback)
  }

  /**
   * 移除错误回调函数
   * @param callback - 要移除的回调函数
   */
  removeErrorCallback(callback: (error: GameErrorInfo) => void): void {
    const index = this.errorCallbacks.indexOf(callback)
    if (index > -1) {
      this.errorCallbacks.splice(index, 1)
    }
  }

  /**
   * 添加恢复回调函数
   * @param callback - 恢复回调函数
   */
  addRecoveryCallback(callback: (error: GameErrorInfo) => boolean): void {
    this.recoveryCallbacks.push(callback)
  }

  /**
   * 移除恢复回调函数
   * @param callback - 要移除的回调函数
   */
  removeRecoveryCallback(callback: (error: GameErrorInfo) => boolean): void {
    const index = this.recoveryCallbacks.indexOf(callback)
    if (index > -1) {
      this.recoveryCallbacks.splice(index, 1)
    }
  }

  /**
   * 获取错误历史记录
   * @returns 错误历史记录数组
   */
  getErrorHistory(): GameErrorInfo[] {
    return [...this.errorHistory]
  }

  /**
   * 获取错误统计信息
   * @returns 错误统计对象
   */
  getErrorStats(): {
    totalErrors: number
    errorsByType: Record<string, number>
    errorsByLevel: Record<string, number>
    recentErrors: number
    recoveredErrors: number
    gameState: GameState
  } {
    const errorsByType: Record<string, number> = {}
    const errorsByLevel: Record<string, number> = {}
    const recentThreshold = Date.now() - 300000 // 最近5分钟

    let recentErrors = 0
    let recoveredErrors = 0

    this.errorHistory.forEach(error => {
      errorsByType[error.type] = (errorsByType[error.type] || 0) + 1
      errorsByLevel[error.level] = (errorsByLevel[error.level] || 0) + 1
      
      if (error.timestamp > recentThreshold) {
        recentErrors++
      }
      
      if (error.recovered) {
        recoveredErrors++
      }
    })

    return {
      totalErrors: this.errorHistory.length,
      errorsByType,
      errorsByLevel,
      recentErrors,
      recoveredErrors,
      gameState: this.gameState
    }
  }

  /**
   * 清除错误历史记录
   */
  clearErrorHistory(): void {
    this.errorHistory = []
  }

  /**
   * 销毁错误处理器
   */
  destroy(): void {
    this.renderErrorHandler.destroy()
    this.audioErrorHandler.destroy()
    this.storageErrorHandler.destroy()
    this.errorCallbacks = []
    this.recoveryCallbacks = []
    this.clearErrorHistory()
  }
}

/**
 * 全局游戏错误处理器实例
 */
export const gameErrorHandler = new GameErrorHandler()